home *** CD-ROM | disk | FTP | other *** search
- Path: xanth!cs.odu.edu!Amiga-Request
- From: Amiga-Request@cs.odu.edu (Amiga Sources/Binaries Moderator)
- Newsgroups: comp.sources.amiga
- Subject: v90i168: process - spawn multiple child processes, keeping track of them, Part01/01
- Message-ID: <12485@xanth.cs.odu.edu>
- Date: 11 May 90 00:52:48 GMT
- Sender: news@cs.odu.edu
- Reply-To: rickf@theweav.cts.com (Rick Flower)
- Lines: 504
- Approved: tadguy@cs.odu.edu (Tad Guy)
- X-Mail-Submissions-To: Amiga@cs.odu.edu
- X-Post-Discussions-To: comp.sys.amiga
-
- Submitted-by: rickf@theweav.cts.com (Rick Flower)
- Posting-number: Volume 90, Issue 168
- Archive-name: examples/process/part01
-
- This Routine will Spawn a "child" process multiple times and attempt to
- keep track of each of the various processes that have been started at
- that point. The program basically creates a "modified" workbench startup
- message that is sent to each routine (there is a different message for
- each process that is spawned -- that way you can send different data to
- the different processes) and that routine "reads" the extra information
- from the WBStartup Message. This program will then keep an array of
- information about the child processes. After all processes have been
- spawned, it will "wait" for each and every child process to complete, and
- then delete the memory segments allocated for the child task with the
- UnLoadSeg call of AmigaDos.
-
- #!/bin/sh
- # This is a shell archive. Remove anything before this line, then unpack
- # it by saving it into a file and typing "sh file". To overwrite existing
- # files, type "sh file -c". You can also feed this as standard input via
- # unshar, or by typing "sh <file", e.g.. If this archive is complete, you
- # will see the following message at the end:
- # "End of archive 1 (of 1)."
- # Contents: child.c makefile_child makefile_parent parent.c
- # Wrapped by tadguy@xanth on Thu May 10 20:52:31 1990
- PATH=/bin:/usr/bin:/usr/ucb ; export PATH
- if test -f 'child.c' -a "${1}" != "-c" ; then
- echo shar: Will not clobber existing file \"'child.c'\"
- else
- echo shar: Extracting \"'child.c'\" \(6295 characters\)
- sed "s/^X//" >'child.c' <<'END_OF_FILE'
- X/*lint -idh0:lc/compiler_headers/ */
- X/*lint -e562 assume ellipsis after comma */
- X/*lint -e607 allow parameter substitution */
- X/*lint -e537 allow repeated include files */
- X/*lint -e544 allow text on #endif lines */
- X/*lint -e565 allow use of struct ptrs within prototypes before definition */
- X/*lint +fvr */
- X
- X/****************************************************************************
- X* FILE : CHILD.C March 21,1990 *
- X*---------------------------------------------------------------------------*
- X* This Routine is made to do true Multi-Tasking within the Amiga Dos System *
- X* It has the code specially written to make sure that NONE of the variables *
- X* used are global and the only variables used are dynamically allocated. *
- X* The only variables that ARE global are static strings, etc. that won't be *
- X* changing at all through program operation. *
- X*---------------------------------------------------------------------------*
- X* This Routine was put together with many hours of piecing together parts *
- X* of code from various authors (many of which I can't remember anymore (:-<)*
- X* some of the info coming from C-A and much of it coming from other sources *
- X* I would certainly like to thank those of you out there that donate your *
- X* own code so that others (like myself!) can learn more about the Amiga! *
- X* *
- X* DISCLAIMER *
- X* *
- X* This program is put into the Public Domain AS-IS and is NOT guaranteed to *
- X* be free from bugs,etc.. (insert standard BS here!) *
- X* *
- X* Rick Flower *
- X* P.O. Box 3907 *
- X* Torrance, Ca. 90510 *
- X* UUCP : {hplabs!hp-sdd ucsd nosc}!crash!theweav!rickf *
- X****************************************************************************/
- X#include <stdio.h>
- X#include <stdlib.h>
- X#include <fcntl.h>
- X#include <exec/types.h>
- X#include <exec/ports.h>
- X#include <exec/io.h>
- X#include <exec/memory.h>
- X#include <workbench/startup.h>
- X#include <proto/dos.h>
- X#include <proto/exec.h>
- X
- X#define strlen __builtin_strlen
- Xextern int strlen __ARGS((char *));
- Xvoid main(void);
- Xextern struct WBStartup *WBenchMsg;
- X
- X/*---------------------------------------------------------------------*/
- X/*- The Following Structure will Enable the Parent Program to Send us -*/
- X/*- a Set of Parameters through the typical Workbench Startup Message -*/
- X/*- without Sending another message to/from the parent.. The Address -*/
- X/*- of the WBStartup Message is Stored by the Startup Code (Asm code) -*/
- X/*- in the External Global Variable called WBenchMsg.. So, we just -*/
- X/*- Cast it to another data type and we're all set! -*/
- X/*- -*/
- X/*- For Usage other than this demo code, just remove the x_coord and -*/
- X/*- y_coord variables and place your own variables to be passed to the-*/
- X/*- child routine.. MAKE SURE THAT THE PARENT ALSO HAS THESE!! -*/
- X/*---------------------------------------------------------------------*/
- Xstruct OurWBenchMsg
- X{
- X struct WBStartup MyMess; /*- Actual Workbench Startup Msg -*/
- X long process_num; /*- Process Number from Parent -*/
- X int x_coord; /*- X Coordinate for Position -*/
- X int y_coord; /*- Y Coordinate for Position -*/
- X};
- X
- X/*------------------------------------------------------------------------*/
- X/*- The Following Line of Code Tells the Compiler to use THIS Version of -*/
- X/*- "_main" Instead of the Library version. We have refefined this to -*/
- X/*- just call the TinyMain routine instead to make it NOT open any I/O -*/
- X/*- Windows... (This suggestion was read on the Lattice Support BBS) -*/
- X/*------------------------------------------------------------------------*/
- Xvoid _main(char *cl) { _tinymain(cl); }
- X
- X/*------------------------------------------------------------------------*/
- X/*- The Following Structure is a Dynamically Allocated structure that we -*/
- X/*- use for ANY and ALL variables used in this program so no variables -*/
- X/*- can overlap and harm another executing child process of this code -*/
- X/*------------------------------------------------------------------------*/
- Xstruct InternalStruct
- X{
- X struct OurWBenchMsg *MyMess;
- X char window[80];
- X char buffer[80];
- X long i;
- X int fh;
- X FILE *fp;
- X};
- X
- Xstruct InternalStruct *IS;
- X
- X/*-------------------------------------------------------------------------*/
- X/*- Main Routine Starts Here! -*/
- X/*-------------------------------------------------------------------------*/
- Xvoid main(void)
- X{
- X IS = AllocMem((ULONG)sizeof(struct InternalStruct),MEMF_CLEAR | MEMF_PUBLIC);
- X if (IS)
- X {
- X IS->MyMess = (struct OurWBenchMsg *)WBenchMsg;
- X sprintf(IS->window,"con:%d/%d/200/70/TEMP-%ld",IS->MyMess->x_coord,IS->MyMess->y_coord,IS->MyMess->process_num);
- X sprintf(IS->buffer,"Process # %04ld\n",IS->MyMess->process_num);
- X IS->fh = open(IS->window,O_RDWR,0);
- X if (IS->fh)
- X {
- X for (IS->i = 0; IS->i < 15; IS->i++)
- X write(IS->fh,IS->buffer,strlen(IS->buffer));
- X sprintf(IS->buffer,"vd0:temp%04ld.dat",IS->MyMess->process_num);
- X IS->fp = fopen(IS->buffer,"w");
- X if (IS->fp)
- X {
- X fprintf(IS->fp,"This Message is from Process #%ld\n\n",IS->MyMess->process_num);
- X fclose(IS->fp);
- X }
- X write(IS->fh,IS->buffer,strlen(IS->buffer));
- X for (IS->i = 0; IS->i < 150000; IS->i++) ;
- X close(IS->fh);
- X }
- X FreeMem(IS,(ULONG)sizeof(struct InternalStruct));
- X }
- X}
- END_OF_FILE
- if test 6295 -ne `wc -c <'child.c'`; then
- echo shar: \"'child.c'\" unpacked with wrong size!
- fi
- # end of 'child.c'
- fi
- if test -f 'makefile_child' -a "${1}" != "-c" ; then
- echo shar: Will not clobber existing file \"'makefile_child'\"
- else
- echo shar: Extracting \"'makefile_child'\" \(1064 characters\)
- sed "s/^X//" >'makefile_child' <<'END_OF_FILE'
- X#%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
- X#% Make the "child" Program %
- X#%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
- X
- X#%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
- X#% Define Global Logical Assignments %
- X#%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
- XBLINK = LC:blink
- XLC_REGFLAGS = -cfist -v
- XLC = LC:lc
- XLIB = LIB:
- X
- X#%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
- X#% Define How to Link the Entire Program # %
- X#%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
- Xchild: child.o
- X BLINK <WITH <
- X FROM $(LIB)catchresnr.o + child.o
- X TO child LIBRARY LIB:lc.lib LIB:amiga.lib
- X<
- X
- X#%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
- X#% What Each File Depends On %
- X#%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
- Xchild.o : child.c
- X $(LC) $(LC_REGFLAGS) child
- X
- END_OF_FILE
- if test 1064 -ne `wc -c <'makefile_child'`; then
- echo shar: \"'makefile_child'\" unpacked with wrong size!
- fi
- # end of 'makefile_child'
- fi
- if test -f 'makefile_parent' -a "${1}" != "-c" ; then
- echo shar: Will not clobber existing file \"'makefile_parent'\"
- else
- echo shar: Extracting \"'makefile_parent'\" \(1094 characters\)
- sed "s/^X//" >'makefile_parent' <<'END_OF_FILE'
- X#%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
- X#% Make the "parent" Program %
- X#%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
- X
- X#%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
- X#% Define Global Logical Assignments %
- X#%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
- XBLINK = LC:blink
- XLC_REGFLAGS = -cfist -b0 -m0 -r0 -s
- XLC_DBGFLAGS = -b0 -m0 -r0 -s -d4
- XLC = LC:lc
- XLIB = LIB:
- X
- X#%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
- X#% Define How to Link the Entire Program # %
- X#%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
- Xparent: parent.o
- X BLINK <WITH <
- X FROM $(LIB)c.o + parent.o
- X TO parent LIBRARY LIB:lc.lib
- X<
- X
- X#%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
- X#% What Each File Depends On %
- X#%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
- Xparent.o : parent.c
- X $(LC) $(LC_REGFLAGS) parent
- X
- END_OF_FILE
- if test 1094 -ne `wc -c <'makefile_parent'`; then
- echo shar: \"'makefile_parent'\" unpacked with wrong size!
- fi
- # end of 'makefile_parent'
- fi
- if test -f 'parent.c' -a "${1}" != "-c" ; then
- echo shar: Will not clobber existing file \"'parent.c'\"
- else
- echo shar: Extracting \"'parent.c'\" \(11246 characters\)
- sed "s/^X//" >'parent.c' <<'END_OF_FILE'
- X/*lint -idh0:lc/compiler_headers/ */
- X/*lint -e562 assume ellipsis after comma */
- X/*lint -e607 allow parameter substitution */
- X/*lint -e537 allow repeated include files */
- X/*lint -e544 allow text on #endif lines */
- X/*lint -e565 allow use of struct ptrs within prototypes before definition */
- X/*lint +fvr */
- X
- X/****************************************************************************
- X* FILE : PARENT.C March 21,1990 *
- X*---------------------------------------------------------------------------*
- X* This Routine will Spawn a "child" process multiple times and attempt to *
- X* keep track of each of the various processes that have been started at *
- X* that point. The program basically creates a "modified" workbench startup *
- X* message that is sent to each routine (there is a different message for *
- X* each process that is spawned -- that way you can send different data to *
- X* the different processes) and that routine "reads" the extra information *
- X* from the WBStartup Message. This program will then keep an array of *
- X* information about the child processes. After all processes have been *
- X* spawned, it will "wait" for each and every child process to complete, and *
- X* then delete the memory segments allocated for the child task with the *
- X* UnLoadSeg call of AmigaDos. *
- X*---------------------------------------------------------------------------*
- X* This Routine was put together with many hours of piecing together parts *
- X* of code from various authors (many of which I can't remember anymore (:-<)*
- X* some of the info coming from C-A and much of it coming from other sources.*
- X* I would certainly like to thank those of you out there that donate your *
- X* own code so that others (like myself!) can learn more about the Amiga! *
- X* *
- X* DISCLAIMER *
- X* *
- X* This program is put into the Public Domain AS-IS and is NOT guaranteed to *
- X* be free from bugs,etc.. (insert standard BS here!) *
- X* *
- X* Rick Flower *
- X* P.O. Box 3907 *
- X* Torrance, Ca. 90510 *
- X* UUCP : {hplabs!hp-sdd ucsd nosc}!crash!theweav!rickf *
- X****************************************************************************/
- X#include <stdio.h>
- X#include <stdlib.h>
- X#include <exec/types.h>
- X#include <exec/ports.h>
- X#include <exec/io.h>
- X#include <exec/memory.h>
- X#include <devices/serial.h>
- X#include <intuition/intuition.h>
- X#include <libraries/dosextens.h>
- X#include <workbench/startup.h>
- X#include <proto/dos.h>
- X#include <proto/exec.h>
- X#include <proto/intuition.h>
- X#include <proto/graphics.h>
- X
- X/*------------------------------------------------------*/
- X/*- Put all Defines Here for PreProcessor Substitution -*/
- X/*------------------------------------------------------*/
- X#define FILE_2_LOAD "child" /*- Filename of Child to Load -*/
- X#define STACK_SIZE 5000L /*- Default Child's Stack Size-*/
- X
- X/*---------------------------------------------------------------------*/
- X/*- The Following Structure will Enable the Parent Program to Send us -*/
- X/*- a Set of Parameters through the typical Workbench Startup Message -*/
- X/*- without Sending another message to/from the parent.. The Address -*/
- X/*- of the WBStartup Message is Stored by the Startup Code (Asm code) -*/
- X/*- in the External Global Variable called WBenchMsg.. So, we just -*/
- X/*- Cast it to another data type and we're all set! -*/
- X/*- -*/
- X/*- For Usage other than this demo code, just remove the x_coord and -*/
- X/*- y_coord variables and place your own variables to be passed to the-*/
- X/*- child routine.. MAKE SURE THAT THE CHILD ALSO HAS THESE!! -*/
- X/*---------------------------------------------------------------------*/
- Xstruct OurWBenchMsg
- X{
- X struct WBStartup MyMess; /*- Actual Workbench Startup Msg -*/
- X long process_num; /*- Process Number from Parent -*/
- X int x_coord; /*- X Coordinate for Position -*/
- X int y_coord; /*- Y Coordinate for Position -*/
- X};
- X
- X/*-------------------------------------------------------------------------*/
- X/*- The Following Structure Allows the Parent Process to Keep Track on a -*/
- X/*- few items that are unique to each child process spawned. Mainly, the -*/
- X/*- Message Port of the Child and the WBenchStartup Message that is sent -*/
- X/*- along with keeping tabs on which child is which.. -*/
- X/*-------------------------------------------------------------------------*/
- Xstruct MyChild
- X{
- X struct MsgPort *Port;
- X struct OurWBenchMsg *StartMsg;
- X long ChildNumber;
- X};
- X
- X/*------------------------------------------*/
- X/*- Define All Program Function Prototypes -*/
- X/*------------------------------------------*/
- Xchar *Initialize_System(void);
- Xint Spawn_Child(char *process_name);
- Xvoid DeInitialize_System(void);
- X
- X/*--------------------------------------------*/
- X/*- Define Global Variables for System Usage -*/
- X/*--------------------------------------------*/
- Xstruct MsgPort *Parent_Port;
- Xstruct MyChild *kids[32] = { NULL };
- Xint CurrentKid;
- XBPTR Child_Code_Addr;
- Xlong ChildNumber = 0;
- Xint x_coord = 10, y_coord = 10;
- X
- X/*----------------------------------------------------------------------*/
- X/*- Open Required Ports & Allocate Workbench Message & Load Child Code -*/
- X/*----------------------------------------------------------------------*/
- Xchar *Initialize_System(void)
- X{
- Xchar *p = NULL;
- X
- X/*------------------------------------------------------------------*/
- X/*- Open a Message Port for Communication with all Child Processes -*/
- X/*------------------------------------------------------------------*/
- X Parent_Port = CreatePort((char *)"WWIV_Main",0L);
- X if (!Parent_Port) p = (char *)"Unable to Open a Message Port..\n";
- X
- X/*-----------------------------------------------------*/
- X/*- Attempt to Load the Program into a Memory Segment -*/
- X/*-----------------------------------------------------*/
- X if (!p)
- X {
- X Child_Code_Addr = LoadSeg(FILE_2_LOAD);
- X if (!Child_Code_Addr)
- X {
- X DeletePort(Parent_Port);
- X p = (char *)"Unable to Load Child Code..\n";
- X }
- X }
- X CurrentKid = -1;
- X return(p);
- X}
- X
- X/*------------------------------------------------------------------------*/
- X/*- Spawn a Child Process & Save Information for Child Resource Tracking -*/
- X/*------------------------------------------------------------------------*/
- Xint Spawn_Child(char *process_name)
- X{
- X CurrentKid++;
- X kids[CurrentKid] = AllocMem((ULONG)sizeof(struct MyChild),MEMF_CLEAR | MEMF_PUBLIC);
- X if ( !kids[CurrentKid] ) { CurrentKid--; return(1); }
- X
- X/*---------------------------------------------------------------------*/
- X/*- Allocate Memory for the Workbench Startup Message & Initialize it -*/
- X/*---------------------------------------------------------------------*/
- X kids[CurrentKid]->StartMsg = AllocMem((ULONG)sizeof(struct OurWBenchMsg),MEMF_CLEAR | MEMF_PUBLIC);
- X if (!kids[CurrentKid]->StartMsg) return(1);
- X kids[CurrentKid]->StartMsg->MyMess.sm_Message.mn_ReplyPort = Parent_Port;
- X kids[CurrentKid]->StartMsg->MyMess.sm_Message.mn_Length = sizeof(struct OurWBenchMsg);
- X
- X/*----------------------------------------------------------*/
- X/*- Create and Start the Child Process & Check for Success -*/
- X/*----------------------------------------------------------*/
- X kids[CurrentKid]->Port = CreateProc(process_name,0L,Child_Code_Addr,STACK_SIZE);
- X if (kids[CurrentKid]->Port)
- X {
- X ChildNumber++;
- X kids[CurrentKid]->ChildNumber = ChildNumber;
- X kids[CurrentKid]->StartMsg->process_num = kids[CurrentKid]->ChildNumber;
- X kids[CurrentKid]->StartMsg->x_coord = x_coord;
- X kids[CurrentKid]->StartMsg->y_coord = y_coord;
- X x_coord += 20;
- X y_coord += 20;
- X printf("Spawning Child #%08ld - %04d : %04d\r",
- X kids[CurrentKid]->ChildNumber,x_coord,y_coord);
- X PutMsg(kids[CurrentKid]->Port,(struct Message *)kids[CurrentKid]->StartMsg);
- X return(0);
- X }
- X else return(1);
- X}
- X
- X/*-----------------------------------------------------------------------*/
- X/*- Unload the Program Segments, Free Workbench Msg Memory, Delete Port -*/
- X/*-----------------------------------------------------------------------*/
- Xvoid DeInitialize_System(void)
- X{
- Xstruct OurWBenchMsg *temp;
- Xint i,a;
- X
- X/*------------------------------------------------------------------------*/
- X/*- Wait for Each and Every Child to Complete and ReplyMsg() to Us Here! -*/
- X/*------------------------------------------------------------------------*/
- X for (i=0; i < ChildNumber; i++)
- X {
- X printf("\nWaiting for a Child to Complete..\n");
- X WaitPort(Parent_Port);
- X temp = (struct OurWBenchMsg *)GetMsg(Parent_Port);
- X/*----------------------------------------------------------------------*/
- X/*- See which child Came in so we only free the resources it used, not -*/
- X/*- others -*/
- X/*----------------------------------------------------------------------*/
- X a = 0;
- X while (kids[a]->StartMsg->process_num != temp->process_num) a++;
- X printf("Child Structure Located @ Address #%02d\n",a);
- X if (kids[a]->StartMsg) FreeMem(kids[a]->StartMsg,(ULONG)sizeof(struct OurWBenchMsg));
- X if (kids[a]) FreeMem(kids[a],(ULONG)sizeof(struct MyChild));
- X }
- X
- X/*------------------------------------------------------------------*/
- X/*- Unload the Child's Code (all children MUST be done Executing!) -*/
- X/*------------------------------------------------------------------*/
- X printf("\nUnloading Children's Code, & Deinitializing System..\n");
- X UnLoadSeg(Child_Code_Addr); /*- Dump Program Segments -*/
- X DeletePort(Parent_Port); /*- Delete Communications!-*/
- X}
- X
- X/*-------------------------------------------------------------------------*/
- X/*- Main Routine Starts Here! -*/
- X/*-------------------------------------------------------------------------*/
- Xvoid main(void)
- X{
- Xchar *p;
- X
- X p = Initialize_System();
- X if (p)
- X printf("%s\n\n",p);
- X else
- X {
- X printf("Initialization Complete...\n");
- X if (Spawn_Child("Child_1") == 1) printf("Error!\n");
- X if (Spawn_Child("Child_2") == 1) printf("Error!\n");
- X if (Spawn_Child("Child_3") == 1) printf("Error!\n");
- X if (Spawn_Child("Child_4") == 1) printf("Error!\n");
- X if (Spawn_Child("Child_5") == 1) printf("Error!\n");
- X if (Spawn_Child("Child_6") == 1) printf("Error!\n");
- X DeInitialize_System();
- X }
- X}
- END_OF_FILE
- if test 11246 -ne `wc -c <'parent.c'`; then
- echo shar: \"'parent.c'\" unpacked with wrong size!
- fi
- # end of 'parent.c'
- fi
- echo shar: End of archive 1 \(of 1\).
- cp /dev/null ark1isdone
- MISSING=""
- for I in 1 ; do
- if test ! -f ark${I}isdone ; then
- MISSING="${MISSING} ${I}"
- fi
- done
- if test "${MISSING}" = "" ; then
- echo You have the archive.
- rm -f ark[1-9]isdone
- else
- echo You still need to unpack the following archives:
- echo " " ${MISSING}
- fi
- ## End of shell archive.
- exit 0
- --
- Mail submissions (sources or binaries) to <amiga@cs.odu.edu>.
- Mail comments to the moderator at <amiga-request@cs.odu.edu>.
- Post requests for sources, and general discussion to comp.sys.amiga.
-